package com.fosss.stack;

/**
 * 模拟简单计算器
 */
public class Calculator {
    public static void main(String[] args) {
        String example="1-2*8+1";//这个运算有bug TODO
        //创建一个数栈，一个符号栈
        ArrayStack2 numStack=new ArrayStack2(10);
        ArrayStack2 operStack=new ArrayStack2(10);
        int index=0;//用于扫描
        int num1=0;
        int num2 = 0;
        int res=0;
        int oper=' ';//用来存放每次扫描得到的char
        String keepNumber="";//用来拼接字符串
        while(true){
            //一次得到example的每一个值
            char c = example.substring(index, index + 1).charAt(0);

            //判断c是符号还是数字
            if(numStack.isCh(c)){
                //如果c是符号，判断符号栈是否为空
                //如果为空，直接入栈
                if(operStack.isEmpty()){
                    operStack.push(c);
                }else{
                    //如果符号栈不为空，就进行比较 若当前符号的优先级小于等于栈中符号的优先级，就需要从数栈中pop出两个数，从符号栈中pop出一个符号
                    //todo 错的-》进行运算，将结果push到数栈，然后将当前符号push到符号栈，如果当前符号优先级大于符号栈的，就直接入栈
                    //一直pop，直到符号栈的操作符的优先级大于栈顶元素或者栈为空
                    while(operStack.priority(c)<=operStack.priority(operStack.peek())){
                        oper = operStack.pop();
                        num1= numStack.pop();
                        num2 = numStack.pop();
                        res=numStack.cal(num1,num2,oper);
                        numStack.push(res);
                        if(operStack.isEmpty()){
                            break;
                        }
                    }
                        operStack.push(c);
                }
            }else {
                //不是符号，直接将数字存入数栈
                //当前代码有bug，不能处理多位数
//                numStack.push(c-48);//注意这里的c为字符型，所以要-48！！！！！！！！！！！！！！！！
                //需要定义一个字符串进行拼接多位数
                keepNumber+=c;

                //判断keepNumber是不是最后一位，是最后一位则直接入栈
                if(index==example.length()-1){
                    numStack.push(Integer.parseInt(keepNumber));
                }else {
                    //判断该值的下一位是不是数字，如果下一位是符号，则直接将c存入数栈 注意这里不要改变index的值
                    if(operStack.isCh(example.substring(index+1,index+2).charAt(0))){
                        numStack.push(Integer.parseInt(keepNumber));
                        //非常关键，一定要将字符串清空
                        keepNumber="";
                    }
                }
            }
            //将index加一，并判断是否到达字符串最后一个值
            index++;
            if(index>=example.length()){
                break;
            }
        }
        //当表达式扫描完毕，就顺序地从数栈和符号栈中pop出相应的书和符号并进行运算
        while (true){
            if(operStack.isEmpty()){
                break;
            }
            num1=numStack.pop();
            num2=numStack.pop();
            oper=operStack.pop();
            res=numStack.cal(num1,num2,oper);
            numStack.push(res);
        }
        //数栈剩下的最后一个数字就是表达式的结果
        res=numStack.pop();
        System.out.println(example+"="+res);
    }
}

class ArrayStack2{
    private int maxSize;//栈的大小
    private int[] stack;//数组模拟栈
    private int top=-1;//表示栈顶

    //构造器
    public ArrayStack2(int maxSize){
        this.maxSize = maxSize;
        //将数组初始化！！！！！！！！！！！！！！！！！
        stack = new int[maxSize];
    }

    //栈满
    public boolean isFull(){
        return top==maxSize-1;
    }
    //栈空
    public boolean isEmpty(){
        return top==-1;
    }

    //入栈
    public void push(int value){
        //先判断栈是否满
        if(isFull()){
            throw new RuntimeException("栈满");
        }
        top++;
        stack[top]=value;
    }

    //出栈
    public int pop(){
        //判断是否为空
        if(isEmpty()){
            throw new RuntimeException("栈空");
        }
        int value=stack[top];
        top--;
        return value;
    }

    //遍历栈，从栈顶开始遍历
    public void list(){
        //判断是否栈空
        if(isEmpty()){
            throw new RuntimeException("栈空");
        }
        for(int i = top;i>=0;i--){
            System.out.printf("stack[%d]=%d\n",i,stack[i]);
        }
    }
    //返回运算符的优先级，用数字代表优先级，数字越大，优先级越大
    public int priority(int ch){
        if(ch=='*'||ch=='/'){
            return 1;
        }else if (ch == '+'||ch =='-') {
            return 0;
        }else {
            return -1;
        }
    }

    //判段是否为运算符
    public boolean isCh(char ch){
        return ch=='+'||ch=='-'||ch=='*'||ch=='/';
    }

    //执行运算
    public int cal(int num1,int num2,int ch){
        int result=0;//用来存放运算结果
        switch (ch){
            case '+':
                result= num1+num2;
                break;
            case '-':
                result= num2-num1;//注意运算顺序！！！！！！！！！！
                break;
            case '*':
                result= num1*num2;
                break;
            case '/':
                result= num2/num1;//注意运算顺序！！！！！！！！！
                break;
            default:
                break;
        }
        return result;
    }
    //获取符号栈栈顶的符号,但不是pop
    public int peek(){
        return stack[top];
    }
}















